package com.qianzhou.page.controller;

import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixProperty;
import com.qianzhou.common.pojo.Products;
import com.qianzhou.page.feign.ProductFeign;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

/**
 * @Author: qian.zhou
 * @Description: PageController
 * @Date Created in 2021-09-12-11:29
 * @Modified By:
 */
@RestController
@RequestMapping("/page")
public class PageController {
    @Autowired
    private RestTemplate restTemplate;
    @Autowired
    private DiscoveryClient discoveryClient;
    @Autowired
    private ProductFeign productFeign;

    @GetMapping("/getPort")
    public String getProductServerPort() {
        String url = "http://service-product/service/port/";
        return restTemplate.getForObject(url, String.class);
    }

    /**
     * 功能描述 通过Ribbon负载均衡的方式获取到实例的信息
     * 并且使用Hystrix熔断器，加入请求的超时时间的熔断
     *
     * @param
     * @return
     * @author qian.zhou
     * @date 2021/9/12
     */
    @HystrixCommand(
            threadPoolKey = "getProductServerPort2",
            threadPoolProperties = {
                    @HystrixProperty(name = "coreSize", value = "1"), // 核心线程数
                    @HystrixProperty(name = "maxQueueSize", value = "20") //等待队列长度
            }
    )
    // 设置网络延迟的时间为2秒
    @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "2000")
    @GetMapping("/getPort2")
    public String getProductServerPort2() {
        String url = "http://service-product/service/port/";
        return restTemplate.getForObject(url, String.class);
    }


    /**
     * 功能描述 加入了反馈机制，如果直接向用户报错那么是不友好的，应该使用一个临时数据，也就是反馈机制的数据
     *
     * @param
     * @return java.lang.String
     * @author qian.zhou
     * @date 2021/9/13
     */
    @HystrixCommand(
            threadPoolKey = "getProductServerPort3",
            threadPoolProperties = {
                    @HystrixProperty(name = "coreSize", value = "1"),// 核心线程数
                    @HystrixProperty(name = "maxQueueSize", value = "20") // 等待队列长度
            },
            fallbackMethod = "getTempPort"
    )
    @GetMapping("/getPort3")
    public String getProductServerPort3() {
        String url = "http://service-product/service/port";
        return restTemplate.getForObject(url, String.class);
    }

    /**
     * 功能描述 兜底的反馈数据
     *
     * @param
     * @return
     * @author qian.zhou
     * @date 2021/9/13
     */
    public String getTempPort() {
        return "我是一个假的微服务端口";
    }

    /**
     * 功能描述 Hystrix的熔断降级处理
     *
     * @param
     * @return java.lang.String
     * @author qian.zhou
     * @date 2021/9/13
     */

    @HystrixCommand(
            threadPoolKey = "getProductServerPort4",
            threadPoolProperties = {
                    @HystrixProperty(name = "coreSize", value = "1"),
                    @HystrixProperty(name = "maxQueueSize", value = "20")
            },
            // commandProperties熔断的一些细节属性配置
            commandProperties = {
                    // 每一个属性都是一个HystrixProperty
                    // 定义超时时间
                    @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "2000"),
                    // 统计时间窗口
                    @HystrixProperty(name = "metrics.rollingStats.timeInMilliseconds", value = "8000"),
                    // 统计时间窗口内的最小请求数
                    @HystrixProperty(name = "circuitBreaker.requestVolumeThreshold", value = "2"),
                    // 统计时间窗口内的错误数量百分比的阈值
                    @HystrixProperty(name = "circuitBreaker.errorThresholdPercentage", value = "50"),
                    // 自我修复时的活动窗口的时间长度
                    @HystrixProperty(name =
                            "circuitBreaker.sleepWindowInMilliseconds", value = "3000"),
            },
            // 兜底数据回退逻辑的方法
            fallbackMethod = "myFallBack" // 回退方法
    )
    @RequestMapping("getPort4")
    public String getProductServerPort4() {
        String url = "http://service-product/service/port";
        return restTemplate.getForObject(url, String.class);
    }

    /**
     * 功能描述 定义回退方法，返回预设默认值
     * 注意：该方法形参和返回值与原始方法保持一致
     *
     * @param
     * @return java.lang.String
     * @author qian.zhou
     * @date 2021/9/13
     */

    public String myFallBack() {
        return "-1"; // 返回一个兜底数据
    }


    /**
     * 功能描述 使用Feign的信息调用服务获取实例的处理结果
     *
     * @param id
     * @return com.qianzhou.common.pojo.Products
     * @author qian.zhou
     * @date 2021/9/13
     */

    @RequestMapping("/getData/{id}")
    public Products findDataById(@PathVariable("id") Integer id) {
        Products products = productFeign.query(id);
        System.out.println(products);
        return products;
    }

    /**
     * 功能描述 使用Feign的信息调用服务获取实例的处理结果
     *
     * @param
     * @return
     * @author qian.zhou
     * @date 2021/9/13
     */
    @RequestMapping("/getPort5")
    public String getProductServerPort5() {
        return productFeign.getPort();
    }
}
